/*
 * Logistician.java
 *
 * Created on 13. Juni 2007, 11:50
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package sbc;

import java.util.*;
import corso.lang.*;
import sbc.corso.*;
import sbc.corso.Sensor;
import sbc.corso.SensorConsumer;
import sbc.corso.util.*;
import org.xvsm.api.core.*;
import org.xvsm.client.ClientCapi;
import sbc.fact.*;
import sbc.factory.SensorFeature;

/**
 *
 * @author mustermark
 */
public class Logistician extends Worker {
    
    private String name;
    private CorsoVarOid unitChannelOid, readyUnitChannelOid;
    private MozartBridge mozartBridge;
    private static Capi capi;
    //private CorsoPipe uninspectedSensorChannel;
    //private CorsoPipe inspectedSensorChannel;
    
    /*public void read (CorsoData data) throws CorsoDataException {
        StringBuffer structName = new StringBuffer ();

        int arity = data.getStructTag (structName);
        if (arity != 1) {
          System.out.println ("arity = " + arity);
          throw new CorsoDataException ();
        }
        //number = data.getInt ();
        if(!structName.toString().equals("SensorOid")) {
               System.out.println ("unknown struct: " + structName);
            throw new CorsoDataException ();
        }
            
        
        oid = new CorsoVarOid();
        data.getShareable(sensorOid);
        
     }

    public void write (CorsoData data) throws CorsoDataException {
        data.putStructTag ("SensorOid", 1);
        data.putShareable(sensorOid);
        //data.putShareable (nextOid);
    }*/

    
    public Logistician() {
        super();
        //oid = new CorsoVarOid();
        
        /*if (args.length != 1) {
            System.out.println("URL needed!");
            System.out.println("Usage: java -cp <classpath> org.xvsm.example.Fifo http://localhost:8084/xvsm-0.8.3\n using embeded core");
            // use embeded xvsm core
            capi = CapiFactory.createCapi();
            //capi = new ClientCapi("http://localhost:8084/xvsm-0.8.3");
            //capi = new ClientCapi("http://localhost:8084/xvsm-0.8.3");
            //capi = new ClientCapi("http://localhost:8084/xvsm-0.8.3");
        } else {
        // Get an instance of the capi and initialize it.
        // Capi capi = CapiFactory.createCapi();
          capi = new ClientCapi(args[0]);
        }*/
        capi.init(true);
        /*try {
            ContainerRef cref = sbc.util.Util.getOrCreateNamedContainer(capi, sbc.xvsm.Defaults.CONTAINER.toString(), CoordinationTypes.FIFO);
            //UI ui = new UI(capi, cref);
            //logger.info("Container: " + cref);
        } catch(Exception ex) { 
            //ex.printStackTrace(); 
            //logger.error("Error creating Container", ex);
        }*/
        
        MozartBridge bridge = new MozartBridge(capi);
    }
    /**
     * Creates a new instance of Logistician
     */
    public Logistician(String n) {
        this();
        name = n;
        
        /*CorsoVarOid uninspectedSensorChannelOid = new CorsoVarOid();
        //CorsoVarOid inspectedSensorChannelOid = new CorsoVarOid();
        try {
            uninspectedSensorChannelOid = con.getNamedVarOid("uninspectedSenors", site, null, false, CorsoConnection.NO_TIMEOUT);
            //inspectedSensorChannelOid = con.getNamedConstOid("inspectedSenors", site, null, false, CorsoConnection.NO_TIMEOUT);
        } catch(CorsoException e) {
            System.out.println("Couldn't retrieve sensor channels for: " +n);
            System.out.println(e);
            System.out.println(e.getMessage());
            System.exit(-10);
            //throw new BridgeException();

        }*/
        
        // create the channel object ********************************************
        //uninspectedSensorChannel = new CorsoPipe(uninspectedSensorChannelOid);
        //inspectedSensorChannel = new CorsoPipe(inspectedSensorChannelOid);
        /*System.out.println("Channels created:");
        System.out.println(uninspectedSensorChannel);
        System.out.println(inspectedSensorChannel);*/
        unitChannelOid = new CorsoVarOid();
        readyUnitChannelOid = new CorsoVarOid();
        try {
            unitChannelOid = con.getNamedVarOid("units", site, null, false, CorsoConnection.NO_TIMEOUT);
            readyUnitChannelOid = con.getNamedVarOid("readyUnits", site, null, false, CorsoConnection.NO_TIMEOUT);
        } catch(Exception e) {
            System.out.println("error getting sensorchannel...");
            e.printStackTrace();
            
        } 
        
        
        UnitConsumer unitConsumer = new UnitConsumer(this, unitChannelOid);
        unitConsumer.start();
        
        /*Runnable sensorCatcher = new Runnable() {
            public void run() {
                for (;;) {
                    String name =null;
                    try {
                        CorsoVarOid oid = uninspectedSensorChannel.next();
                        
                        //materialStreamNames.add();
                        
                    } catch(CorsoException e) {
                        System.out.println("Couldn't retrieve rawMaterialStream for Factory: " +name);
                        System.out.println(e);
                    }   
                    
                }
            }
        };
        Thread catcherThread = new Thread(boardAndSensorCatcher);
        catcherThread.start();*/
        
        /*try {
            oid = con.createVarOid(con.getCurrentStrategy());
            //sensorOid.writeString(education, CorsoConnection.NO_TIMEOUT);
            //sensorOid.writeShareable(new Sensor(), CorsoConnection.NO_TIMEOUT);
            workChannel.append(oid);
        
        } catch(CorsoException e) {
            System.out.println("Error wrinting sensorOid to " + workChannel);
            System.out.println(e);
        }*/
            
        
        /*try {
            CorsoConstOid rawMaterialOid = con.getOrCreateNamedConstOid (con.getCurrentStrategy(), name, null);
            final RawMaterialStream rawMaterial = new RawMaterialStream(rawMaterialOid);
            Runnable rawMaterialLine = new Runnable() {
                public void run() {
                    for (;;) {
                        try {
                            Module mod = rawMaterial.readNextModule();
                            System.out.println ("New data: " + mod);
                            //moduleQueque.add(mod);
                            if(mod instanceof Sensor) {
                                //uninspectedSensorQueque.add((Sensor)mod);

                            } else if(mod instanceof Board) {
                               // boardQueque.add((Board)mod);
                            } else {
                                System.out.println("Unknown RawMaterial");
                            }
                        } catch(Exception e) {
                            System.out.println("Error getting next Module ");
                            System.out.println(e);
                        }
                        
                    }
                }
            };
            Thread rawMaterialLineThread = new Thread(rawMaterialLine);
            rawMaterialLineThread.start();
            System.out.println ("rawmaterialline for " + name + " established!");

        } catch(Exception e) {
            System.out.println("Error creating MaterialStream");
            System.out.println(e);
        }*/
        
        
        /*Vector users = new Vector ();
        users.addElement (new String ("*"));
        try {
            // create new service types ********************************************
            con.addServiceType ("InspectionExecutionService", "SensorInspection", CorsoConnection.USER_ADMINISTRATED, users, "Desc");
            System.out.println ("Service type 'InspectionExecutionService' created ");
            con.addServiceType ("AssemblyExecutionService", "UnitAssembly", CorsoConnection.USER_ADMINISTRATED, users, "Desc");
            System.out.println ("Service type 'AssemblyExecutionService' created ");
            con.addServiceType ("DeliveryExecutionService", "UnitDelivery", CorsoConnection.USER_ADMINISTRATED, users, "Desc");
            System.out.println ("Service type 'DeliveryExecutionService' created ");

        } catch(Exception e) {
            System.out.println("Error adding Service Types ");
            System.out.println(e);
        }
        */
        //Thread inspectionThread = new Thread(new InspectionExecution());
        //inspectionThread.start();
        
        
    }
    
    //static Sensor tmpSensor = null;
    
    public void workOn(CorsoShareable sh) {
        Unit u = (Unit)sh;
        CorsoTopTransaction tx = null;
        
        try {
            tx = con.createTopTransaction ();
        } catch(CorsoException e) {
            System.out.println("Couldn't create TopTransaction");
            System.out.println(e);
        }
        System.out.println("starting UNIT TO BRIDGE Transaction");
        
        try {
            UnitChannel unitChannel = new UnitChannel(readyUnitChannelOid);
            //Unit unit = new Unit(b, s, second);
            //Sensor s = new Sensor(id, features);
            UnitLinker uLinker = new UnitLinker();
            uLinker.unit = u;
            uLinker.next = con.createConstOid (con.getCurrentStrategy());
            unitChannel.appendModuleLinker(uLinker);
            System.out.println("appended UNIT" + uLinker.unit + " to READY UnitChannel");
        } catch(CorsoException e) {
            System.out.println("Couldn't send Unit to Bridge!!!!!!");
            System.out.println(e);
        }
    }
    
    
    /*JobApplicationNotifier inspectorApplicationNotifier = new JobApplicationNotifier("InspectorApplication", site, con, 
            new JobApplicationReceiver(){
                public void shareableRegistered(CorsoShareable shareable) {
                    Registration reg = (Registration)shareable;
                    reg.getApplicant();
                    reg.getEducation();
                }
                public void objectModified(CorsoShareable shareable) {
                    CorsoVarOid oid = (CorsoVarOid)shareable; 
                    //CorsoData data = con.createData();
                    
                    
                }
            }
    ) {
        protected CorsoVarOid createEmptyShareable() {
            oid = new CorsoVarOid();
            return oid;
        }
    };*/
    static int cnt;
    
    public static void main (String [] args) {
        
        if(args.length == 1) {
            //throw new RuntimeException("args must be length 2 (CAPI)");
            capi = new ClientCapi(args[0]);
            System.out.println ("CALL: Logistician <name>");
            
            Logistician i = new Logistician("Logistician0");
            System.out.println ("strating test instance: Logistician0");
        } else if(args.length == 2){
            capi = new ClientCapi(args[0]);
            System.out.println ("CALL: Logistician <name>");
            
            Logistician i = new Logistician(args[1]);
            System.out.println ("strating instance: "+args[1]);
        
        } else {
            throw new RuntimeException("args legnth must be 1 or 2");
        }
        
    }
}
